package com.tangji.signaltower.runners;

import com.alibaba.fastjson.JSON;
import com.fqgj.common.utils.CollectionUtils;
import com.tangji.signaltower.bean.MarketDataEntity;
import com.tangji.signaltower.controller.GrayListController;
import com.tangji.signaltower.enums.ProductEnum;
import com.tangji.signaltower.service.dao.entity.MockBinaryTradeEntity;
import com.tangji.signaltower.service.dao.entity.UserAccessEntity;
import com.tangji.signaltower.service.dao.entity.UserWanningListEntity;
import com.tangji.signaltower.service.dao.inter.MockBinaryTradeDao;
import com.tangji.signaltower.service.dao.inter.UserAccessDao;
import com.tangji.signaltower.service.dao.inter.UserWanningListDao;
import com.tangji.signaltower.websocket.session.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: sm
 * Date: 2020-09-17
 * Time: 18:33
 */
@Service

@EnableScheduling
public class WarningListInit {

    private static final Logger logger = LoggerFactory.getLogger(WarningListInit.class);

    public static Set<String> fakeUsersCodeSet = new HashSet<>();

    public static Map<String, MockMarketEntity> fakeUsersOrderPriceMap = new HashMap<>();

    public static Map<String, String> userCodeAndTokenMap = new HashMap<>();

    public static Map<String, MockMarketEntity> fakeUsersOrderPriceMapNew = new HashMap<>();

    @Autowired
    private UserWanningListDao userWanningListDao;

    @Autowired
    private UserAccessDao userAccessDao;

    @Autowired
    private MockBinaryTradeDao mockBinaryTradeDao;

//    @Scheduled(cron = "0/10 * * * * ?")
    public void initWanningList() {
        logger.info("== 初始化黑名单列表 开始 ==");
        List<UserWanningListEntity> allWarningUsers = userWanningListDao.getAllWarningUsers();
        if (CollectionUtils.isEmpty(allWarningUsers)) {
            logger.info("== 初始化黑名单列表 size=0 ==");
            return;
        }

        Set<String> fakeUsersTokenSet = new HashSet<>();
        Set<String> fakeUsersCodeSet2 = new HashSet<>();
        Map<String, String> userCodeAndTokenMap2 = new HashMap<>();
        allWarningUsers.forEach(allWarningUser -> {
            UserAccessEntity userAccessEntity = userAccessDao.selectUserAccessByUserCode(allWarningUser.getUserCode());
            if (userAccessEntity != null) {
                logger.info("== 初始化加载灰色名单 ==,userCode:{},token:{}", allWarningUser.getUserCode(), userAccessEntity.getToken());
                fakeUsersTokenSet.add(userAccessEntity.getToken());
                fakeUsersCodeSet2.add(allWarningUser.getUserCode());
                userCodeAndTokenMap2.put(allWarningUser.getUserCode(), userAccessEntity.getToken());
            } else {
                logger.error("== 初始化加载灰色名单 查找token失败==,userCode:{}", allWarningUser.getUserCode());
            }
        });

        logger.info("== 初始化黑名单列表 完成 ==,size:{}", fakeUsersTokenSet.size());
        SessionFactory.fakeUsersSet = fakeUsersTokenSet;
        fakeUsersCodeSet = fakeUsersCodeSet2;
        userCodeAndTokenMap = userCodeAndTokenMap2;
    }

//    @Scheduled(cron = "0/6 * * * * ?")
    public void createMockTrade() {
        List<String> userCodes = new ArrayList<>();
        for (String userCode : fakeUsersCodeSet) {
            userCodes.add(userCode);
        }


        //获取批量等待结算的订单
        List<MockBinaryTradeEntity> listByUserCodesAndStatus = mockBinaryTradeDao.getLatestByUserCodesAndStatusAndTime(userCodes, 1);
        if (CollectionUtils.isEmpty(listByUserCodesAndStatus)) {
            fakeUsersOrderPriceMap = fakeUsersOrderPriceMapNew;
            logger.info("== 获取批量等待结算的订单 ==,size:{}", 0);
            return;
        }

        logger.info("== 获取批量等待结算的订单 ==,size:{}", listByUserCodesAndStatus.size());

        listByUserCodesAndStatus.forEach(trade -> {
            if (userCodeAndTokenMap.containsKey(trade.getUserCode())) {
                String token = userCodeAndTokenMap.get(trade.getUserCode());
                String warningListRedisKey = GrayListController.getWarningListRedisKey(token, trade.getProductCode(), trade.getExpectDeadline().getTime() / 1000);

                //开盘价格
                BigDecimal openingPrice = trade.getOpeningPrice();

                //买涨买跌 0 跌 1涨
                boolean isUp = trade.getTrendType() == 1;

                BigDecimal closingPrice = BigDecimal.ZERO;
                ProductEnum enumByProductCode = ProductEnum.getEnumByProductCode(trade.getProductCode());
                if (enumByProductCode == null) {
                    logger.error("== 获取批量等待结算的订单 产品类型不存在==,userCode:{}", trade.getUserCode());
                    return;
                }

                int tailMore = new Random().nextInt(9);
                String newTailMore = "";
                for (int i = 0; i < enumByProductCode.getTailNum(); i++) {
                    if (i == enumByProductCode.getTailNum() - 1) {
                        newTailMore += tailMore + "";
                    } else {
                        newTailMore += "0";
                    }
                }

                BigDecimal tailB = new BigDecimal("0." + newTailMore);
                logger.info("== 获取批量等待结算的订单 ==,warningListRedisKey:{},orignPrice:{},tailB:{}", warningListRedisKey, openingPrice, tailB);

                if (isUp) {
//                    double downRate = (1.0 + new Random().nextInt(5)) / 1000;
                    closingPrice = openingPrice.subtract(tailB);
                } else {
//                    double upRate = (1.0 + new Random().nextInt(5)) / 1000;
                    closingPrice = openingPrice.add(tailB);
                }

                logger.info("== 获取批量等待结算的订单 ==,warningListRedisKey:{},orignPrice:{},tailB:{},isUp:{},closingPrice:{}", warningListRedisKey, openingPrice, tailB, isUp, closingPrice);
                logger.info("== 获取批量等待结算的订单 ==,warningListRedisKey:{},orignPrice:{},newP:{}", warningListRedisKey, openingPrice, closingPrice.toString());
                MockMarketEntity mockMarketEntity = new MockMarketEntity(closingPrice.toString(), trade.getExpectDeadline().getTime() / 1000, false);
                mockMarketEntity.setTrendType(trade.getTrendType())
                        .setStartPrice(trade.getOpeningPrice().toString())
                        .setTradeNo(trade.getTradeNo());
                fakeUsersOrderPriceMapNew.put(warningListRedisKey, mockMarketEntity);

                logger.info("== 获取批量等待结算的订单 8989 ==" + warningListRedisKey + "-" + closingPrice.toString());
                mockNext3Point(openingPrice.toString(), trade.getExpectDeadline().getTime() / 1000, token, trade.getProductCode(), closingPrice.toString());

                logger.info("== 获取批量等待结算的订单 ==,warningListRedisKey:{},price:{}", warningListRedisKey, closingPrice.toString());
            } else {
                logger.info("== 获取批量等待结算的订单 不包含当前User==,userCode:{}", trade.getUserCode());
            }
        });

        fakeUsersOrderPriceMap = fakeUsersOrderPriceMapNew;
    }


    /**
     * @param firstTime     开始出发mock的时间点  毫秒
     * @param firstNewPrice 第一个mock的点的
     * @param sessionId     用户的token
     * @param productCode   用户的产品
     *                      <p>
     *                      第一个点被mock之后 需要mock后续的3个点 达到平滑的要求
     */
    private static void mockNext3Point(String originPrice, Long firstTime, String sessionId, String productCode, String firstNewPrice) {

        ProductEnum enumByProductCode = ProductEnum.getEnumByProductCode(productCode);
        if (enumByProductCode == null) {
            return;
        }

        //计算出第一次的正常值和mock值之间的差值是多少
        BigDecimal subtract = new BigDecimal(firstNewPrice).subtract(new BigDecimal(originPrice)).abs();

        BigDecimal fnp = new BigDecimal(firstNewPrice);
        //接下来的后面三个点
        logger.info("==获取批量等待结算的订单  sendFakeUser 第一次的价格 ==,fnp:{}", fnp);
        for (int i = -3; i < 4; i++) {
            if (i == 0) {
                continue;
            }
            boolean isUp = new Random().nextInt(10) > 5;
            int tailMore = 1 + new Random().nextInt(8);
            String newTailMore = "";
            for (int j = 0; j < enumByProductCode.getTailNum(); j++) {
                if (j == enumByProductCode.getTailNum() - 1) {
                    newTailMore += tailMore + "";
                } else {
                    newTailMore += "0";
                }
            }

            BigDecimal tailB = new BigDecimal("0." + newTailMore);

            BigDecimal tempValue = BigDecimal.ZERO;
            if (isUp) {
                tempValue = fnp.add(tailB).setScale(enumByProductCode.getTailNum(), RoundingMode.HALF_UP);
            } else {
                tempValue = fnp.subtract(tailB).setScale(enumByProductCode.getTailNum(), RoundingMode.HALF_UP);
            }

            long expectDeadLineTime = (firstTime + i);
            String warningListRedisKey = GrayListController.getWarningListRedisKey(sessionId, productCode, firstTime + i);
            MockMarketEntity mockMarketEntity = new MockMarketEntity()
                    .setPrice(tempValue.toString())
                    .setExpectDeadLineTime(expectDeadLineTime)
                    .setTrendType(3)
                    .setCanMock(false);

            logger.info("== 获取批量等待结算的订单 sendFakeUser isUp ==,isUp:{},newUpdateValue:{},origin:{},temp:{},warningListRedisKey:{},mockMarketEntity:{}", isUp, tailB, originPrice, tempValue, warningListRedisKey, JSON.toJSONString(mockMarketEntity));
            logger.info("== 获取批量等待结算的订单 8989 ==" + warningListRedisKey + "-" + tempValue);
            WarningListInit.fakeUsersOrderPriceMapNew.put(warningListRedisKey, mockMarketEntity);
        }
    }


    public static void main(String[] args) {
        BigDecimal closingPrice = BigDecimal.ZERO;
        BigDecimal openingPrice = new BigDecimal("0.24326000");
        BigDecimal tailB = new BigDecimal("0.000001");
        closingPrice = openingPrice.subtract(tailB);

        System.err.println(closingPrice);
    }

}
